#include "gut/MeshElements.h"

using namespace Gut;

bool MeshElements::CreateFromDesc(const MeshElementsDesc &desc)
{

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, desc.vertexStride * desc.vertexNum, desc.vertexheader, desc.usage);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, desc.indiceNum * desc.indiceStride, desc.indiceHeader, desc.usage);

    for (int i = 0; i < desc.numLayout; i++)
    {
        const auto &l = desc.layout[i];

        glEnableVertexAttribArray(l.index);

        if (l.type == GL_FLOAT)
        {
            glVertexAttribPointer(l.index, l.size, l.type, l.normalized,
                                  desc.vertexStride, (void *)l.offset);
        }
        else if (l.type == GL_INT)
        {
            glVertexAttribIPointer(l.index, l.size, l.type, desc.vertexStride, (void *)l.offset);
        }
    }

    glBindVertexArray(0);

    this->numIndices = desc.indiceNum;
    this->faceType = desc.face;
    this->indiceStride = desc.indiceStride;

    if (desc.indiceStride == 2)
    {
        this->indiceType = GL_UNSIGNED_SHORT;
    }
    else if (desc.indiceStride == 4)
    {
        this->indiceType = GL_UNSIGNED_INT;
    }
    else if (desc.indiceStride == 1)
    {
        this->indiceType = GL_UNSIGNED_BYTE;
    }
    else
    {
        return false;
    }

    glBindVertexArray(0);

    return true;
}

void MeshElements::DrawElements() const
{
    glBindVertexArray(VAO);
    glDrawElements(this->faceType, this->numIndices, this->indiceType, (void *)(this->startIndex * this->indiceStride));
    glBindVertexArray(0);
}

void MeshElements::DrawInstanced(unsigned int count) const
{
    glBindVertexArray(VAO);
    glDrawElementsInstanced(this->faceType, this->numIndices, this->indiceType, 0, count);
    glBindVertexArray(0);
}
